package com.jxmcloud.business.cut.service.impl.user;

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jxmcloud.business.cut.dtoCommon.BagInfoDto;
import com.jxmcloud.business.cut.dtoCommon.CashDetailInfoDto;
import com.jxmcloud.business.cut.json.DataConfigService;
import com.jxmcloud.business.cut.model.database.DBUserAwardInfo;
import com.jxmcloud.business.cut.model.database.DBUserBag;
import com.jxmcloud.business.cut.service.database.IUserAwardInfoDBService;
import com.jxmcloud.business.cut.service.user.IUserBagService;
import com.jxmcloud.business.cut.service.user.IUserCashDetailListService;
import com.jxmcloud.business.cut.service.user.IUserFlowService;
import com.jxmcloud.business.cut.util.MyTool;
import com.jxmcloud.business.cut.vo.UserOrderTranVo;
import com.jxmcloud.business.cut.vo.json.ConfigProgressVo;
import com.jxmcloud.business.cut.vo.user.PlayerInfoVo;
import com.jxmcloud.business.cut.vo.user.UserCashDetailItemVo;
import com.jxmcloud.business.cut.vo.user.UserCashDetailVo;
import com.jxmcloud.business.cut.vo.user.UserOrderListVo;
import com.xlcloud.platform.api.config.Constant;
import com.xlcloud.platform.util.DateUtil;
import com.xlcloud.platform.util.PublicUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
public class UserCashDetailListServiceImpl implements IUserCashDetailListService {
    @Resource
    private DataConfigService dataConfigService;
    @Resource
    private IUserFlowService userFlowService;
    @Resource
    private IUserBagService userBagService;
    @Resource
    private IUserAwardInfoDBService userAwardInfoDBService;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveToDb(PlayerInfoVo player, String key) {
        // 无
        return true;
    }

    private boolean insertIntoData(PlayerInfoVo player, UserCashDetailItemVo cashInfo) {
        DBUserAwardInfo dbUserAwardInfo = new DBUserAwardInfo();
        dbUserAwardInfo.setUid(player.getBase().getUid());
        dbUserAwardInfo.setActivityId(player.getActivity().getActivityId());
        dbUserAwardInfo.setAwardId(cashInfo.getId());
        dbUserAwardInfo.setAwardCount(cashInfo.getCount());
        Integer createTime = cashInfo.getTime();
        dbUserAwardInfo.setCreateTime(cn.hutool.core.date.DateUtil.date(createTime.longValue() * 1000L));
        dbUserAwardInfo.setTitle(cashInfo.getTitle());
        dbUserAwardInfo.setProgressId(cashInfo.getProgressId());
        if(cashInfo.getSpecId() > 0){
            dbUserAwardInfo.setSpecId(cashInfo.getSpecId());
        }
        if(cashInfo.getOrderId() > 0){
            dbUserAwardInfo.setOrderId(cashInfo.getOrderId());
        }

        return userAwardInfoDBService.insertIntoData(dbUserAwardInfo);
    }


    private boolean revertInsertIntoData(PlayerInfoVo player, UserCashDetailItemVo cashInfo) {
        DBUserAwardInfo dbUserAwardInfo = new DBUserAwardInfo();
        dbUserAwardInfo.setUid(player.getBase().getUid());
        dbUserAwardInfo.setActivityId(player.getActivity().getActivityId());
        dbUserAwardInfo.setAwardId(cashInfo.getId());
        dbUserAwardInfo.setAwardCount(cashInfo.getCount());
        Integer createTime = cashInfo.getTime();
        dbUserAwardInfo.setCreateTime(cn.hutool.core.date.DateUtil.date(createTime.longValue() * 1000L));
        dbUserAwardInfo.setTitle(cashInfo.getTitle());
        dbUserAwardInfo.setProgressId(cashInfo.getProgressId());
        if(cashInfo.getSpecId() > 0){
            dbUserAwardInfo.setSpecId(cashInfo.getSpecId());
        }
        if(cashInfo.getOrderId() > 0){
            dbUserAwardInfo.setOrderId(cashInfo.getOrderId());
        }

        return userAwardInfoDBService.remove(new QueryWrapper<DBUserAwardInfo>()
                .eq("uid", dbUserAwardInfo.getUid())
                .eq("activity_id", dbUserAwardInfo.getActivityId())
                .eq("award_id", dbUserAwardInfo.getAwardId())
                .eq("award_count",dbUserAwardInfo.getAwardCount())
                .eq("title", dbUserAwardInfo.getTitle())
                .eq("progress_id", dbUserAwardInfo.getProgressId())
                .eq(cashInfo.getSpecId() > 0, "spec_id", cashInfo.getSpecId())
                .eq(cashInfo.getOrderId() > 0, "order_id", cashInfo.getOrderId()));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean loadFromDb(PlayerInfoVo player, Integer uid) {
        List<DBUserAwardInfo> cashList = userAwardInfoDBService.selectAll(uid, player.getActivity().getActivityId());
        if (ObjectUtil.isNull(cashList)) {
            return false;
        }
        for (DBUserAwardInfo cashDetail : cashList) {
            UserCashDetailItemVo newCash = new UserCashDetailItemVo();
            newCash.setId(cashDetail.getAwardId());
            newCash.setCount(cashDetail.getAwardCount());
            newCash.setTitle(cashDetail.getTitle());
            Date createTime = cashDetail.getCreateTime();
            newCash.setTime((int) (createTime.getTime() / 1000));
            newCash.setProgressId(cashDetail.getProgressId());
            if(ObjectUtil.isNotNull(cashDetail.getSpecId())){
                newCash.setSpecId(cashDetail.getSpecId());
            }
            if(ObjectUtil.isNotNull(cashDetail.getOrderId())){
                newCash.setOrderId(cashDetail.getOrderId());
            }
            this.makeCashDetail(player, newCash, false);
        }

        return true;
    }


    @Override
    public boolean register(PlayerInfoVo player, Integer uid) {
        // 无
        return true;
    }

    @Override
    public boolean addNewCashDetail(PlayerInfoVo player, UserCashDetailItemVo newCash) {
        this.makeCashDetail(player, newCash, true);
        return true;
    }

    @Override
    public UserCashDetailItemVo getCashDetailItemByProgressId(PlayerInfoVo player, Integer progressId) {
        UserCashDetailVo cashDetail = player.getUserCashDetailVo();
        UserCashDetailItemVo data = cashDetail.getProgressList().get(progressId);
        if (ObjectUtil.isNull(data)) {
            return null;
        }
        return data;
    }

    // 填充用户数据
    private void makeCashDetail(PlayerInfoVo player, UserCashDetailItemVo newCash, boolean insertDb) {
        player.getUserCashDetailVo().getProgressList().put(newCash.getProgressId(), newCash);
        if (newCash.getOrderId() > 0 && newCash.getSpecId() > 0) {
            player.getUserCashDetailVo().getOrderList().put(newCash.getOrderId() + Constant.LINE_XHX + newCash.getSpecId(), newCash);
        }
        if (insertDb) {
            // 插入到数据库
            this.insertIntoData(player, newCash);
        }
    }

    // 回滚填充用户数据
    private void revertMakeCashDetail(PlayerInfoVo player, UserCashDetailItemVo newCash, boolean insertDb) {
        player.getUserCashDetailVo().getProgressList().put(newCash.getProgressId(), newCash);
        if (newCash.getOrderId() > 0 && newCash.getSpecId() > 0) {
            player.getUserCashDetailVo().getOrderList().put(newCash.getOrderId() + Constant.LINE_XHX + newCash.getSpecId(), newCash);
        }
        if (insertDb) {
            // 插入到数据库
            this.revertInsertIntoData(player, newCash);
        }
    }

    // 是否已有这个步骤的奖励
    private boolean isExistProgressCash(PlayerInfoVo player, Integer progressId) {
        UserCashDetailItemVo cashData = player.getUserCashDetailVo().getProgressList().get(progressId);
        if (ObjectUtil.isNotNull(cashData)) {
            return true;
        }
        return false;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean makeCashDetailByProgressId(PlayerInfoVo player, Integer progressId) {
        // 是否已有
        boolean hasProgressCash = this.isExistProgressCash(player, progressId);
        if (hasProgressCash) {
            return false;
        }

        BagInfoDto awardItem = userFlowService.calcProgressAward(player, progressId);
        if (ObjectUtil.isNull(awardItem)) {
            return false;
        }
        //
        ConfigProgressVo progressConfig = dataConfigService.getConfigProgressConfig(progressId);
        Integer[] award = progressConfig.getAward();
        Long timeData = DateUtil.dateToTime(DateUtil.newDate());
        String newTitle = Optional.ofNullable(progressConfig.getAwardTitle()).map(d -> d.replace("$", (award[1]) + "")).orElse(null);
        UserCashDetailItemVo newCash = new UserCashDetailItemVo();
        newCash.setId(awardItem.getId());
        newCash.setCount(awardItem.getCount());
        newCash.setTitle(newTitle);
        newCash.setTime(timeData.intValue());
        newCash.setProgressId(progressId);
        this.makeCashDetail(player, newCash, true);
        //
        userBagService.addItem(player, awardItem.getId(), awardItem.getCount());
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean revertMakeCashDetailByProgressId(PlayerInfoVo player, Integer progressId) {
        BagInfoDto awardItem = userFlowService.calcProgressAward(player, progressId);
        if (ObjectUtil.isNull(awardItem)) {
            return false;
        }
        //
        ConfigProgressVo progressConfig = dataConfigService.getConfigProgressConfig(progressId);
        Integer[] award = progressConfig.getAward();
        Long timeData = DateUtil.dateToTime(DateUtil.newDate());
        String newTitle = Optional.ofNullable(progressConfig.getAwardTitle()).map(d -> d.replace("$", (award[1]) + "")).orElse(null);
        UserCashDetailItemVo newCash = new UserCashDetailItemVo();
        newCash.setId(awardItem.getId());
        newCash.setCount(awardItem.getCount());
        newCash.setTitle(newTitle);
        newCash.setTime(timeData.intValue());
        newCash.setProgressId(progressId);
        this.revertMakeCashDetail(player, newCash, true);
        //
        userBagService.revertAddItem(player, awardItem.getId(), awardItem.getCount());
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean makeOrderCashDetailByProgressId(PlayerInfoVo player, Integer progressId) {
        // 是否已有
        boolean hasProgressCash = this.isExistProgressCash(player, progressId);
        if (hasProgressCash) {
            return false;
        }

        BagInfoDto awardItem = userFlowService.calcProgressAward(player, progressId);
        if (ObjectUtil.isNull(awardItem)) {
            return false;
        }
        Long timeData = DateUtil.dateToTime(DateUtil.newDate());
        // 获取一个未使用的订单
        UserOrderListVo payOrderList = player.getUserOrderListVo();

        HashMap<String, UserCashDetailItemVo> playerOrderList = player.getUserCashDetailVo().getOrderList();
        for (UserOrderTranVo userOrderTranVo : payOrderList.getUserOrderList()) {
            Integer orderId = userOrderTranVo.getOrderId();
            Integer specId = userOrderTranVo.getSpecId();
            UserCashDetailItemVo info = playerOrderList.get(orderId + Constant.LINE_XHX + specId);
            if (ObjectUtil.isNotNull(info)) {
                continue;
            }
            UserCashDetailItemVo newCash = new UserCashDetailItemVo();

            newCash.setId(awardItem.getId());
            newCash.setCount(awardItem.getCount());
            newCash.setTitle(userOrderTranVo.getGoodsName());
            newCash.setTime(timeData.intValue());
            newCash.setOrderId(orderId);
            newCash.setSpecId(specId);
            newCash.setProgressId(progressId);
            this.makeCashDetail(player, newCash, true);
            userBagService.addItem(player, awardItem.getId(), awardItem.getCount());
            return true;
        }
        return false;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean revertMakeOrderCashDetailByProgressId(PlayerInfoVo player, Integer progressId) {
        BagInfoDto awardItem = userFlowService.calcProgressAward(player, progressId);
        if (ObjectUtil.isNull(awardItem)) {
            return false;
        }
        Long timeData = DateUtil.dateToTime(DateUtil.newDate());
        // 获取一个未使用的订单
        UserOrderListVo payOrderList = player.getUserOrderListVo();

        HashMap<String, UserCashDetailItemVo> playerOrderList = player.getUserCashDetailVo().getOrderList();
        for (UserOrderTranVo userOrderTranVo : payOrderList.getUserOrderList()) {
            Integer orderId = userOrderTranVo.getOrderId();
            Integer specId = userOrderTranVo.getSpecId();
            UserCashDetailItemVo info = playerOrderList.get(orderId + Constant.LINE_XHX + specId);
            if (ObjectUtil.isNotNull(info)) {
                continue;
            }
            UserCashDetailItemVo newCash = new UserCashDetailItemVo();

            newCash.setId(awardItem.getId());
            newCash.setCount(awardItem.getCount());
            newCash.setTitle(userOrderTranVo.getGoodsName());
            newCash.setTime(timeData.intValue());
            newCash.setOrderId(orderId);
            newCash.setSpecId(specId);
            newCash.setProgressId(progressId);
            this.revertMakeCashDetail(player, newCash, true);
            userBagService.revertAddItem(player, awardItem.getId(), awardItem.getCount());
            return true;
        }
        return false;
    }

    @Override
    public CashDetailInfoDto packVotoDto(UserCashDetailItemVo vo) {
        CashDetailInfoDto dto = new CashDetailInfoDto();
        dto.setId(vo.getId());
        dto.setCount(vo.getCount());
        dto.setTime(vo.getTime());
        dto.setProgressId(vo.getProgressId());
        dto.setTitle(vo.getTitle());
        dto.setType(2);
        if (MyTool.isTure(vo.getSpecId())) {
            dto.setType(1);
        }

        return dto;
    }

    @Override
    public List<CashDetailInfoDto> packPlayer(PlayerInfoVo player) {
        // 根据此progress 来进行打包
        HashMap<Integer, UserCashDetailItemVo> progressList = player.getUserCashDetailVo().getProgressList();
        if (PublicUtil.isEmpty(progressList)) {
            return null;
        }
        List<CashDetailInfoDto> infoDtoList = progressList.values().stream().map(itemVo -> {
                    CashDetailInfoDto cashDetailInfoDto = new CashDetailInfoDto();
                    cashDetailInfoDto.setTitle(itemVo.getTitle());
                    cashDetailInfoDto.setCount(itemVo.getCount());
                    cashDetailInfoDto.setId(itemVo.getId());
                    cashDetailInfoDto.setTime(itemVo.getTime());
                    cashDetailInfoDto.setProgressId(itemVo.getProgressId());
                    cashDetailInfoDto.setType(2);
                    if (MyTool.isTure(itemVo.getSpecId())) {
                        cashDetailInfoDto.setType(1);
                    }
                    return cashDetailInfoDto;
                })
                .collect(Collectors.toList());
        return infoDtoList;
    }

    @Override
    public void clearCashDetail(PlayerInfoVo player) {
        player.getUserCashDetailVo().getProgressList().clear();
        player.getUserCashDetailVo().getOrderList().clear();

        // 清空数据库
        userAwardInfoDBService.deleteData(player.getBase().getUid(), player.getActivity().getActivityId());
    }
}
